package edu.indiana.cs.b534.torrent.impl;



import java.util.logging.Level;
import java.util.logging.Logger;

import edu.indiana.cs.b534.torrent.StorageManager;
import edu.indiana.cs.b534.torrent.TorrentException;
import edu.indiana.cs.b534.torrent.context.RequestBean;
import edu.indiana.cs.b534.torrent.context.TorrentContext;

public class PieceRequestSender extends Thread{
	private static final int MINUTE = 60000;
	
	private final TorrentContext torrentContext;
	
	private int amountOfDataSentOnThisimeSlice = 0;
	private long startTime = System.currentTimeMillis();
	
	private static Logger logger = Logger.getLogger(TorrentManager.TORRENT_MANAGER_NAME);
	
	public PieceRequestSender(TorrentContext torrentContext) {
		this.torrentContext = torrentContext;
		this.setDaemon(true);
	}

	@Override
	public void run() {
		while(true){
			try {
				StorageManager storageManager = torrentContext.getStorageManager();
				if(storageManager == null){
					Thread.sleep(1000);
					continue;
				}
				if(System.currentTimeMillis() - startTime >= MINUTE){
					startTime = System.currentTimeMillis();
					logger.info("Upload rate for last minutes is "+ amountOfDataSentOnThisimeSlice/1024 + "KB");
					System.out.println("Upload rate for last minutes is "+ amountOfDataSentOnThisimeSlice/1024 + "KB");
					amountOfDataSentOnThisimeSlice = 0;
//				}else if(amountOfDataSentOnThisimeSlice > torrentContext.getBytesLeftToBeDownloaded()){
//					long timeLeftOnThistimeSlice =  MINUTE - (System.currentTimeMillis()-startTime);
//					logger.info("Quote for time time  slice is over, sleeping for  "+ timeLeftOnThistimeSlice + "ms");
//					Thread.sleep(timeLeftOnThistimeSlice);
				}
				
				
				RequestBean request = torrentContext.getRequestQueue().getRequest();
				
				
				
				PieceInfo pieceInfo = storageManager.getPieceInfo(request.getPieceIndex());
				int begin = request.getBegin();
				int length= request.getLength();
				int pieceIndex = request.getPieceIndex();
				if ((request.getBegin() + request.getLength()) <= pieceInfo.getPieceLength()) {


	                byte[] piece = storageManager.getPiece(request.getPieceIndex());
	                byte[] dataToBeSent = new byte[length];

	                //We do this to avoid array index out of bound on last block of the piece
	                System.arraycopy(piece, begin, dataToBeSent, 0, length);
	                try {
	                    request.getPeerInstance().sendPieceMessage(pieceIndex, begin, dataToBeSent);
	                    logger.info("For peer "+ request.getPeerInstance().getID() + " Block for piece "+ pieceIndex + "from " + begin + " and length " + length + " is Added to queue");
	                    //System.out.println("For peer "+ request.getPeerInstance().getID() + " Block for piece "+ pieceIndex + "from " + begin + " and length " + length + " is Added to queue");
	                    amountOfDataSentOnThisimeSlice = amountOfDataSentOnThisimeSlice + length;
	                } catch (TorrentException e) {
	                	if(request.getRetryCount() > 0){
	                		request.reduceRetryCount();
	                		torrentContext.getRequestQueue().addWork(request);
	                	}
	                    logger.severe("Can not send piece to the peer. " + e);
	                }
	            } else {
	                logger.log(Level.SEVERE,request.getPeerInstance().getID() + " is requesting a block " +
	                        "inside the piece " + pieceIndex + ". But I do not have a block with the beginning index " + begin + " and length " + length);
	            }
				
			} catch (Throwable e) {
				e.printStackTrace();
				logger.throwing(this.getClass().getName(), "run", e);
			}
		}
	}

}
